/* eslint-disable no-constant-condition */
import { CHAT_LIST, SELECTED_CHAT } from '@src/const/storeKeys';
import localData from './localData';
import { IChatItem, IChatMessage } from '@src/types/chat';
import dayjs from 'dayjs';
import { generateUUID, getRedMarkdown } from '.';

// 格式化Reader信息
export const getReaderInfo = async (
  reader: any,
  onMessageChange: (msg: string, loading: boolean) => void,
  onError?: (error: string) => void,
) => {
  // 反编码
  const decode = new TextDecoder('utf8');
  let fullText = '';
  let partialData = '';

  while (true) {
    const { value, done } = await reader.read();
    if (done) {
      onMessageChange(fullText, false);
      break;
    } else {
      const raw = decode.decode(value);
      try {
        const jsonRaw = JSON.parse(raw);
        if (jsonRaw.code && jsonRaw.code !== 0) {
          let errMsg = '请求失败，请稍后重试';
          if (jsonRaw.msg.indexOf('429') !== -1) {
            errMsg = `${jsonRaw.msg}, 请求过于频繁，请稍后重试`;
          }
          onError?.(errMsg);
          break;
        }
      } catch (error) {
        // console.log(error);
      }

      // 之前剩下的加上新来的
      partialData += raw;

      // 没有分隔的
      if (partialData.indexOf('\n\n') === -1) {
        continue;
      }
      let items = partialData.split('\n\n');

      partialData = '';
      items = items
        .map((item) => item.replace(/^\s*data: /, ''))
        .filter((item) => item.length > 0)
        .filter((item) => item !== '[DONE]');

      const datas = items
        .map((item) => {
          let json;
          try {
            json = JSON.parse(item);
          } catch (error) {
            // 不能json化说明数据不完整，需要和下一个stream流进行拼接
            partialData = item;
          }
          return json;
        })
        .filter(Boolean);

      for (const data of datas) {
        let text = '';
        // 这里的错误处理待优化
        if (data?.error?.message) {
          text = getRedMarkdown(data?.error?.message);
          // onError?.(data?.error?.message);
        } else {
          text = data?.choices?.[0]?.delta?.content;
        }
        if (text !== undefined) {
          fullText += text;
          onMessageChange(fullText, true);
        }
      }
    }
  }
};

// 获取默认聊天信息，要返回一个函数
export const getDefaultChatItem = (
  options?: Partial<IChatMessage>,
): IChatItem => {
  return {
    name: '新建对话',
    chatId: generateUUID(),
    messages: [],
    createTime: dayjs().unix(),
    updateTime: dayjs().unix(),
    ...options,
  };
};

/*
 注: 后续这里要用indexDB或者后端永久存储
 */

// 获取所有的对话内容
export const getChatList = (): IChatItem[] => {
  return localData.get(CHAT_LIST);
};

// 获取当前的对话内容
export const getCurChatSession = (chatId: string) => {
  return (getChatList().find((item) => item.chatId === chatId) ||
    {}) as IChatItem;
};

// 获取当前活跃的key
export const getSelectedChatId = (): string => {
  return localData.get(SELECTED_CHAT);
};

// 创建新的会话
export const createNewChat = (name?: string): IChatItem => {
  const allSession = getChatList() || [];
  const defaultChatItem = getDefaultChatItem();
  const newSession = { ...defaultChatItem, ...(name ? { name } : {}) };
  allSession.push({ ...defaultChatItem });
  // 更新会话列表
  localData.set(CHAT_LIST, allSession);
  return newSession;
};

// 创建新的消息
export const createMessage = (
  content: string,
  role: IChatMessage['role'],
  options?: Partial<Omit<IChatMessage, 'role'>>,
): IChatMessage => {
  return {
    messageId: generateUUID(), // 唯一id
    role, // 角色
    content, // 消息内容
    createTime: dayjs().unix(), // 创建时间
    model: {}, // 模型内容,maxToken等等
    templateId: '', // 模版id
    isError: false,
    ...options,
  };
};

// 更新当前活跃的key
export const updateSelectedChatID = (chatId: string) => {
  return localData.set(SELECTED_CHAT, chatId);
};

// 更新会话内容
export const updateChatItemInfo = (
  chatId: string,
  chatItem: IChatItem,
): IChatItem[] => {
  const allChatList = getChatList();
  const index = allChatList.findIndex((item) => item.chatId === chatId);

  if (index < 0) {
    return [] as IChatItem[];
  }

  // 更新chatList
  allChatList.splice(index, 1, chatItem);
  localData.set(CHAT_LIST, allChatList);
  return allChatList;
};

// 通过key更新会话内容
export const updateChatItemByKey = <T extends keyof IChatItem>(
  chatId: string,
  key: T,
  value: IChatItem[T],
): { chatList: IChatItem[]; curChatItem: IChatItem } => {
  const curChatItem = {
    ...getCurChatSession(chatId),
    [key]: value,
  };

  return {
    chatList: updateChatItemInfo(chatId, curChatItem),
    curChatItem,
  };
};

// 通过key更新最后一个聊天消息
export const updateChatMessage = (
  chatId: string,
  value: string,
  options?: Partial<IChatMessage>,
): IChatItem => {
  const messages = getCurChatSession(chatId).messages;
  const lastMessage: IChatMessage = {
    ...messages?.pop(),
    content: value,
    ...options,
  } as IChatMessage;

  return updateChatItemByKey(chatId, 'messages', [...messages, lastMessage])
    .curChatItem;
};

// 删除会话内容
export const deleteChatItem = (chatId: string): IChatItem[] => {
  const allChatList = getChatList();
  const index = allChatList.findIndex((item) => item.chatId === chatId);

  if (index < 0) {
    return [] as IChatItem[];
  }

  // 更新chatList
  allChatList.splice(index, 1);
  localData.set(CHAT_LIST, allChatList);
  return allChatList;
};

// 删除聊天消息
export const deleteMessage = (index: number, chatId: string, num = 1) => {
  const curSession = getCurChatSession(chatId);
  const messages = (curSession.messages || []).filter((item) => item.content);
  num ? messages.splice(index, num) : messages.splice(index); // num是删除的条数,如果是0代表全部删除

  return updateChatItemByKey(chatId, 'messages', messages).curChatItem;
};

// 清空所有的对话
export const deleteChatList = (): void => {
  localData.del(SELECTED_CHAT);
  localData.del(CHAT_LIST);
};

export const formatHistoryMessage = (chatId: string, len: number) => {
  const curSession = getCurChatSession(chatId);
  const messages = (curSession.messages || []).filter(
    (item) => item.content && !item.isError,
  );
  const maxLen = len < messages.length - 1 ? len : messages.length - 1;

  return messages
    .slice(messages.length - 1 - maxLen, messages.length - 1)
    .map((item) => ({
      role: item.role,
      content: item.content,
    }));
};
